package com.zh.utils;

import com.zh.config.MinioConfig;
import com.zh.domain.Model.FileMetadata;
import com.zh.domain.Model.UpLoadChunkTmp;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.DeleteResult;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

@Component
@Data
@Slf4j
@RequiredArgsConstructor
public class MinioUtil {

    private final MinioClient client;
    private final MinioConfig config;

    /**
     * 创建存储桶
     *
     * @param bucketName 存储桶名称
     */
    public void createBucket(String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }


    public void upLoadChunk(UpLoadChunkTmp upLoadChunkTmp) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 上传文件流
        String contentType = getContentType(upLoadChunkTmp.getObjectName());
        PutObjectArgs.Builder builder = PutObjectArgs.builder()
                .bucket(upLoadChunkTmp.getBucketName())
                .object(upLoadChunkTmp.getObjectName())
                .stream(upLoadChunkTmp.getStream(), upLoadChunkTmp.getChunkSize(), -1);
        if (contentType != null) {
            builder.contentType(contentType);
        }
        client.putObject(builder.build());
        upLoadChunkTmp.getStream().close();
    }

    public void composeChunk(String bucketName, String objectName, List<ComposeSource> sources) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        client.composeObject(
                ComposeObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .sources(sources)
                        .build()
        );
    }

    public void deleteChunk(String bucketName, List<DeleteObject> deleteObjects, String fileName) {
        try {
            Iterable<Result<DeleteError>> results = client
                    .removeObjects(RemoveObjectsArgs.builder()
                            .bucket(bucketName)
                            .objects(deleteObjects)
                            .build());
            for (Result<DeleteError> result : results) {
                DeleteError deleteError = result.get();
                log.error("error in deleteing object" + deleteError.objectName() + ";" + deleteError.message());
            }
            log.info("删除{}所有分片成功!", fileName);
        } catch (Exception e) {
            log.error("minio删除文件失败{}", e.getMessage(), e);
        }
    }

    public void deleteObject(String bucketName, String objectName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 获取文件地址
     *
     * @param bucketName bucketName bucket名称 lawsweep
     * @param objectName objectName 文件全名称 2024116/1.jpg
     * @return
     */
    public String getUrl(String bucketName, String objectName) {
        return config.getEndpoint() + "/" + bucketName + "/" + objectName;
    }

    public FileMetadata getFileMetaDataFromMinio(String url) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        URL fileUrl = new URL(url);
        String bucketName = config.getBucketName();
        String fullPath = fileUrl.getPath().substring(1);
        String objectName = fullPath.substring(fullPath.indexOf('/') + 1); // 得到 "xxx.jpg"
        // 获取对象信息
        StatObjectResponse stat = client.statObject(
                StatObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build()
        );
        Long fileSize = stat.size();
        String contentType = stat.contentType();
        String fileExtension = getFileExtensionFromContentType(contentType);
        return new FileMetadata(fileSize, fileExtension);
    }

    private String getContentType(String fileName) {
        return URLConnection.guessContentTypeFromName(fileName);
    }

    private String getFileExtensionFromContentType(String contentType) {
        if (contentType == null) {
            return "";
        }
        switch (contentType) {
            // 图片类型
            case "image/webp":
                return "webp";
            case "image/gif":
                return "gif";
            case "image/jpeg":
            case "image/jpg":
                return "jpg";
            case "image/png":
                return "png";
            case "image/svg+xml":
                return "svg";
            case "image/tiff":
                return "tiff";
            case "image/bmp":
                return "bmp";
            case "image/x-icon":
                return "ico";

            // 文档类型
            case "application/pdf":
                return "pdf";
            case "application/msword":
                return "doc";
            case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
                return "docx";
            case "application/vnd.ms-excel":
                return "xls";
            case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
                return "xlsx";
            case "application/vnd.ms-powerpoint":
                return "ppt";
            case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
                return "pptx";

            // 压缩文件
            case "application/zip":
                return "zip";
            case "application/x-rar-compressed":
                return "rar";
            case "application/x-7z-compressed":
                return "7z";
            case "application/x-tar":
                return "tar";
            case "application/gzip":
                return "gz";

            // 文本类型
            case "text/plain":
                return "txt";
            case "text/html":
                return "html";
            case "text/css":
                return "css";
            case "text/javascript":
            case "application/javascript":
                return "js";
            case "application/json":
                return "json";
            case "text/xml":
            case "application/xml":
                return "xml";
            case "text/markdown":
            case "text/x-markdown":
                return "md";

            // 音频类型
            case "audio/mpeg":
                return "mp3";
            case "audio/wav":
                return "wav";
            case "audio/ogg":
                return "ogg";
            case "audio/midi":
                return "midi";
            case "audio/aac":
                return "aac";

            // 视频类型
            case "video/mp4":
                return "mp4";
            case "video/mpeg":
                return "mpeg";
            case "video/quicktime":
                return "mov";
            case "video/x-msvideo":
                return "avi";
            case "video/webm":
                return "webm";
            case "video/x-matroska":
                return "mkv";
            case "video/x-flv":
                return "flv";

            // 字体类型
            case "font/ttf":
                return "ttf";
            case "font/otf":
                return "otf";
            case "font/woff":
                return "woff";
            case "font/woff2":
                return "woff2";

            // 其他常见类型
            case "application/x-shockwave-flash":
                return "swf";
            case "application/vnd.android.package-archive":
                return "apk";
            case "application/x-msdownload":
                return "exe";
            case "application/x-sh":
                return "sh";
            case "application/x-sql":
                return "sql";

            default:
                return "";
        }
    }
}
